﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace GetMyColors
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            GenerateImage();
        }

        private void GenerateImage()
        {
            try
            {
                // This code violates nearly every one of my style guidelines...
                List<string> base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".ToCharArray().Select(c => c.ToString()).ToList();
                string cleaned = textBox1.Text.Replace(" ", "+").ToCharArray().Select(c => c.ToString()).Where(v => base64set.Contains(v)).Aggregate((c, n) => c + n);
                Enumerable.Range(0, cleaned.Length % 4 == 0 ? 0 : 4 - cleaned.Length % 4).ToList().ForEach(i => cleaned += "+");
                string code = Convert.FromBase64String(cleaned).Select(b => b.ToString("X2")).Aggregate((c, n) => c + n);
                string colorspre = code;
                Enumerable.Range(0, colorspre.Length % 6 == 0 ? 0 : 6 - colorspre.Length % 6).ToList().ForEach(i => colorspre += "F");
                List<Color> colors = Enumerable.Range(0, colorspre.Length).Where(x => x % 6 == 0).Select(i => colorspre.Substring(i, 6)).Select(s => ColorTranslator.FromHtml("#" + s)).ToList();
                string validate = Convert.ToBase64String(Enumerable.Range(0, colors.Count * 6).Where(x => x % 2 == 0).Select(x => Convert.ToByte(colors.Select(c => Regex.Replace(ColorTranslator.ToHtml(c), @"\#", "")).Aggregate((c, n) => c + n).Substring(x, 2), 16)).ToArray());

                Bitmap image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
                Enumerable.Range(0, image.Width).ToList().ForEach(x => Enumerable.Range(0, image.Height).ToList().ForEach(y => image.SetPixel(x, y, colors[(int)Math.Floor(((double)x / (double)image.Width) * colors.Count)])));
                pictureBox1.Image = image;

                textBox2.Text = code;
                textBox3.Text = colors.Select(c => ColorTranslator.ToHtml(c)).Aggregate((c, n) => c + " " + n);
                textBox4.Text = validate;
                textBox4.BackColor = textBox1.Text == textBox4.Text ? Color.LightGreen : Color.White;
                button2.Enabled = true;
            }
            catch
            {
                ThrowAmbiguousErrorMessage();
            }
        }

        private static void ThrowAmbiguousErrorMessage()
        {
            // Throw a meaningless error message to the user
            MessageBox.Show("Something bad that I didn't plan on ever happening has just happened.", "Um, oops...", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            try
            {
                textBox1.BackColor = textBox1.Text.Length % 4 == 0 ? Color.LightGreen : Color.LightBlue;
                button1.Enabled = textBox1.Text.Length > 0 && !checkBox1.Checked;

                if (textBox1.Text.Length > 0 && checkBox1.Checked)
                {
                    GenerateImage();
                }
            }
            catch
            {
                ThrowAmbiguousErrorMessage();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                DialogResult d = saveFileDialog1.ShowDialog();
                if (d == DialogResult.OK)
                {
                    pictureBox1.Image.Save(saveFileDialog1.FileName);
                }
            }
            catch
            {
                ThrowAmbiguousErrorMessage();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            MessageBox.Show(
                "This application works by pretending that what you type\n" + 
                "into the box is a Base64 encoded string. It decodes it\n" +
                "into bytes, then encodes sets of three bytes into the\n" + 
                "RGB parts of a color. These colors make up YOUR colors.", 
                "Get My Colors", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            button1.Enabled = !checkBox1.Checked && textBox1.Text.Length > 0;
        }
    }
}
